/*******************************************************************************
 * Copyright (c) 2007 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.classdiagram.parsers.modelgenerator;

import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;


import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;

import com.cea.papyrus.classdiagram.parsers.texteditor.vsldatatypes.IContext;
import com.cea.papyrus.classdiagram.parsers.texteditor.vsldatatypes.VSLPrimitiveTypes;
import com.cea.papyrus.classdiagram.parsers.antlr.VSLLexer;
import com.cea.papyrus.classdiagram.parsers.antlr.VSLParser;

import antlr.RecognitionException;
import antlr.TokenStreamException;


public class VSLGenerator {
	//private Property property;
	private Property property;
	private DataType subdatatype;
	private DataType dataType;
	

	private int context;
	/**
	 * Default Constructor
	 * @param property the property to modify
	 */
	//public TVLGenerator(Property property) {
	//	this.property = property;
	//}
	
	/*public VSLGenerator(OpaqueExpression opaqueExpression) {
		this.opaqueExpression = opaqueExpression;
	}*/
	
	public VSLGenerator(DataType datatype){
		this.dataType = datatype;
	}
	
	/**
	 * Parse the label of the property and modify property attributes.
	 * @param label the label that defines the property
	 * @throws RecognitionException
	 * @throws TokenStreamException
	 */
	public void parseAndModifyProperty(String label) throws RecognitionException, TokenStreamException  {
		VSLLexer lexer = new VSLLexer(new StringReader(label));
    	VSLParser parser = new VSLParser(lexer);
    	parser.nfpValueSpecification();
	}
	
	/**
	 * Parse the label of the property and validate it.
	 * @param label the label that defines the property
	 * @return null if label is valid, else return the message that describes the error.
	 */
	public String parseAndValidateProperty(String text, DataType datatype) {
		String message = null;
		
		// to validate the message : parse it. If no errors, it is ok. If exceptions : not ok. Returns the exception message
		VSLLexer lexer = new VSLLexer(new BufferedReader(new StringReader(text.replace(" ", ""))));
		VSLParser parser = new VSLParser(lexer);
    	parser.setValidation(true);
    	
    	try {
//    		if (!datatype.getAllAttributes().isEmpty()) {
//   				parser.tuple();
//    		}
    		if (datatype.getName().equals(VSLPrimitiveTypes.BOOLEAN)) {
    			parser.booleanLiteral();
    		}
    		if (datatype.getName().equals(VSLPrimitiveTypes.NFPEXPRESSION)) {
    			parser.nfpValueSpecification();
    		}
    		if (datatype.getName().equals(VSLPrimitiveTypes.REAL)) {
   			parser.realLiteral();
    		}
    		if (datatype.getName().equals(VSLPrimitiveTypes.STRING)) {
    			parser.stringLiteral();
    		}
    		if (datatype.getName().equals(VSLPrimitiveTypes.INTEGER)) {
    			parser.integerLiteral();
    		}
    		if (datatype.getName().equals(VSLPrimitiveTypes.UNLIMITEDNATURAL)) {
    			parser.unlimitedLiteral();
    		}
    		if(datatype instanceof Enumeration){
    			parser.enumerationSpecification();
    		}
    		else {
    			parser.tuple();
    		}
    			
    		
    		this.context = parser.getContext();
    	} catch (RecognitionException e) {
    		this.context = parser.getContext();
    		message = e.getLocalizedMessage();
		} catch (TokenStreamException e) {
			this.context = parser.getContext();
			message = e.getLocalizedMessage();
		}
		
		return message;
	}
	
	
	
	public String isTupleValid(String text, DataType datatype, int offset) {
		String message="";
		String[] textSplit;
		String tmp="";
		int auxPosition=0;
		String auxText[];
		
		textSplit = text.split(",");
		if (textSplit.length>0) {
			tmp="";
			if (textSplit[0].length()>0) {
				tmp=textSplit[0].substring(0,1);
			}
			if (!tmp.equals("(")) {
				message = "expected '('; ";
			}
			else {
				textSplit[0]=textSplit[0].substring(1, textSplit[0].length());
			}
			tmp="";
			if (textSplit[0].length()>0) {
				tmp=textSplit[textSplit.length-1].substring(textSplit[textSplit.length-1].length()-1,textSplit[textSplit.length-1].length());
			}
			if (!tmp.equals(")")) {
				message = message + "expected ')'; ";
			}
			else {
				textSplit[textSplit.length-1]=textSplit[textSplit.length-1].substring(0, textSplit[textSplit.length-1].length()-1);				
			}
			for(int i=0; i < datatype.getAllAttributes().size(); i++) {
				property = (Property) datatype.getAllAttributes().get(i);
				if (textSplit.length>i) {
					tmp="";
					if (textSplit[0].length()>0) {
						tmp=textSplit[i].substring(0, textSplit[i].indexOf("=")).trim();
					}	
					if (!property.getName().equals(tmp)) {
						message = message + "missmatching name for: " + property.getName() + "; ";
					}
				}
				else {
					message = message + "missing item for: " + property.getName() + "; ";
				}
			}
 
			if (message.equals("")) {
				if (offset>0){
					auxText=(text.substring(0, offset)).split(",");
					auxPosition = auxText.length-1;
					textSplit[auxPosition]=textSplit[auxPosition].substring(textSplit[auxPosition].indexOf("=")+1);
					property = (Property) datatype.getAllAttributes().get(auxPosition);
					subdatatype = (DataType) property.getType();
					tmp=parseAndValidateProperty (textSplit[auxPosition], subdatatype);
			
					if (tmp!=null) {
						message = message + tmp + "; ";
					}	
				}
				else {
					for (int i=0; i < textSplit.length; i++) {
						textSplit[i]=textSplit[i].substring(textSplit[i].indexOf("=")+1);
						property = (Property) datatype.getAllAttributes().get(i);
						subdatatype = (DataType) property.getType();
						tmp=parseAndValidateProperty (textSplit[i], subdatatype);
    				
						if (tmp!=null) {
							message = message + tmp + "; ";
						}
					}
				}	
					
    		}
    		else {
    			message=message+parseAndValidateProperty (text, datatype);
    		}
    			
		}	
    	if (message.equals("")) {
   			return null;
   		}
   		else {
   			return message;
   		}	
	}
	
	public int getContext () {
		return this.context;
	}
	
	public DataType getSubDataType(){
		return subdatatype;
	}
	}